package com.fitzone.web.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fitzone.common.context.UserContext;
import com.fitzone.common.exception.BaseException;
import com.fitzone.common.exception.OrderBusinessException;
import com.fitzone.model.base.BaseContext;
import com.fitzone.model.dto.*;
import com.fitzone.model.entity.*;
import com.fitzone.model.vo.*;
import com.fitzone.web.mapper.*;
import com.fitzone.web.service.*;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class OrdersServiceImpl extends ServiceImpl<OrdersMapper, Orders> implements OrdersService {

    @Autowired
    private CoachMapper coachMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private CourseMapper courseMapper;
    @Autowired
    private OrdersMapper ordersMapper;
    @Autowired
    private VipMapper vipMapper;
    @Autowired
    private StoreMapper storeMapper;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private RestHighLevelClient client;

    /**
     * 课程订单
     * @param ordersPageDTO
     * @return
     */
    @Override
    public Page<OrdersCourseVO> pageCourse(OrdersPageDTO ordersPageDTO){
//        //创建request对象
//        SearchRequest request = new SearchRequest();
//        //分页查询 即准备DSL语句
//        //获取查询值
//        String number = ordersPageDTO.getNumber();
//        if (number == null || "".equals(number)){
//            request.source().query(QueryBuilders.matchAllQuery());
//        }else {
//            request.source().query(QueryBuilders.matchQuery("number", number));
//        }
//        //获取分页
//        Integer page = ordersPageDTO.getPage();
//        Integer limit = ordersPageDTO.getLimit();
//        request.source().from((page - 1) * limit).size(limit);
//        client.search(request, RequestOptions.DEFAULT);

        Page<Orders> pageOrder = new Page<>(ordersPageDTO.getPage(), ordersPageDTO.getLimit());
        Page<OrdersCourseVO> pageOrderInfo = new Page<>();

        LambdaQueryWrapper<Orders> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(ordersPageDTO.getNumber()!= null,Orders::getNumber, ordersPageDTO.getNumber())
                .orderByDesc(Orders::getCreateTime)
                .eq(Orders::getStatus, 0);

        IPage<Orders> ordersIPage = ordersMapper.selectPage(pageOrder, queryWrapper);
        BeanUtils.copyProperties(ordersIPage, pageOrderInfo,"records");
        List<Orders> records = ordersIPage.getRecords();
        List<OrdersCourseVO> list = records.stream().map(item -> {
            OrdersCourseVO ordersCourseVO = new OrdersCourseVO();
            ordersCourseVO.setPayable(item.getPayable());
            ordersCourseVO.setPayment(item.getPayment());
            ordersCourseVO.setNumber(item.getNumber());
            LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
            userLambdaQueryWrapper.eq(User::getId,item.getUserId());
            User user = userMapper.selectById(item.getUserId());
            ordersCourseVO.setUname(user.getName());
            Course course = courseMapper.selectById(item.getCourseId());
            BeanUtils.copyProperties(course, ordersCourseVO);
            Store store = storeMapper.selectById(course.getStoreId());
            ordersCourseVO.setStoreName(store.getStoreName());
            Coach coach = coachMapper.selectById(item.getCoachId());
            ordersCourseVO.setCoachName(coach.getCoachName());
            return ordersCourseVO;
        }).collect(Collectors.toList());

        pageOrderInfo.setRecords(list);
        return pageOrderInfo;
    }

    /**
     * 教练订单
     * @param ordersPageDTO
     * @return
     */
    @Override
    public Page<OrdersCoachVO> pageCoach(OrdersPageDTO ordersPageDTO) {
        Page<Orders> pageOrder = new Page<>(ordersPageDTO.getPage(), ordersPageDTO.getLimit());
        Page<OrdersCoachVO> pageOrderInfo = new Page<>();

        LambdaQueryWrapper<Orders> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(ordersPageDTO.getNumber() != null,
                        Orders::getNumber,ordersPageDTO.getNumber()).orderByDesc(Orders::getCreateTime)
                .eq(Orders::getStatus,1);
        IPage<Orders> ordersIPage = ordersMapper.selectPage(pageOrder, queryWrapper);
        BeanUtils.copyProperties(ordersIPage, pageOrderInfo,"records");
        List<Orders> records = ordersIPage.getRecords();
        List<OrdersCoachVO> list = records.stream().map(item -> {
            OrdersCoachVO ordersCoachVO = new OrdersCoachVO();
            ordersCoachVO.setNumber(item.getNumber());
            ordersCoachVO.setPayment(item.getPayment());
            ordersCoachVO.setPayable(item.getPayable());
            User user = userMapper.selectById(item.getUserId());
            ordersCoachVO.setUname(user.getName());

            Coach coach = coachMapper.selectById(item.getCoachId());
            ordersCoachVO.setCoachName(coach.getCoachName());
            Store store = storeMapper.selectById(coach.getStoreId());
            ordersCoachVO.setStoreName(store.getStoreName());
            return ordersCoachVO;
        }).collect(Collectors.toList());
        pageOrderInfo.setRecords(list);
        return pageOrderInfo;
    }

    /**
     * 会员订单
     * @param ordersPageDTO
     * @return
     */
    @Override
    public Page<OrdersVipVO> pageVip(OrdersPageDTO ordersPageDTO) {
        Page<Orders> pageOrder = new Page<>(ordersPageDTO.getPage(), ordersPageDTO.getLimit());
        Page<OrdersVipVO> pageOrderInfo = new Page<>();

        LambdaQueryWrapper<Orders> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(ordersPageDTO.getNumber()!= null,Orders::getNumber, ordersPageDTO.getNumber())
                .orderByDesc(Orders::getCreateTime)
                .eq(Orders::getStatus, 2);

        IPage<Orders> ordersIPage = ordersMapper.selectPage(pageOrder, queryWrapper);
        BeanUtils.copyProperties(ordersIPage, pageOrderInfo,"records");
        List<Orders> records = ordersIPage.getRecords();
        List<OrdersVipVO> list = records.stream().map(item -> {
            OrdersVipVO ordersVipVO = new OrdersVipVO();
            ordersVipVO.setNumber(item.getNumber());
            ordersVipVO.setPayment(item.getPayment());
            ordersVipVO.setPayable(item.getPayable());
            User user = userMapper.selectById(item.getUserId());
            ordersVipVO.setUname(user.getName());
            Vip vip = vipMapper.selectById(item.getVipId());
            ordersVipVO.setVtype(vip.getType());
            return ordersVipVO;
        }).collect(Collectors.toList());

        pageOrderInfo.setRecords(list);
        return pageOrderInfo;
    }

    @Override
    public void orderCourse(OrdersCourseDTO ordersCourseDTO) {
        Orders orders = new Orders();
        orders.setNumber(String.valueOf(LocalDateTime.now().toEpochSecond(ZoneOffset.ofHours(8))));
        orders.setCoachId(ordersCourseDTO.getCoachId());
        orders.setCourseId(ordersCourseDTO.getCourseId());
        orders.setPayment(ordersCourseDTO.getPayment());
        orders.setUserId(UserContext.getCurrentId());
        orders.setStatus(0);
        LambdaQueryWrapper<Course> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ordersCourseDTO.getCourseId() != null,Course::getId,ordersCourseDTO.getCourseId());
        List<Course> courses = courseMapper.selectList(queryWrapper);
        for (Course course : courses) {
            orders.setPayable(course.getPrice());
            Integer max = course.getMax();
            LambdaQueryWrapper<Orders> queryWrapper2 = new LambdaQueryWrapper<>();
            queryWrapper2.eq(course.getId() != null,Orders::getCourseId, course.getId());
            Integer count = ordersMapper.selectCount(queryWrapper2);
            if (count == max){
                throw new BaseException("人数已满，请预约其他课程");
            }
        }
        ordersMapper.insert(orders);
    }

    @Override
    public void orderCoach(OrdersCoachDTO ordersCourseDTO) {
        Orders orders = new Orders();
        orders.setNumber(String.valueOf(LocalDateTime.now().toEpochSecond(ZoneOffset.ofHours(8))));
        orders.setCoachId(ordersCourseDTO.getCoachId());
        orders.setPayment(ordersCourseDTO.getPayment());
        orders.setUserId(UserContext.getCurrentId());
        orders.setStatus(1);
        LambdaQueryWrapper<Coach> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ordersCourseDTO.getCoachId() != null,Coach::getId,ordersCourseDTO.getCoachId());
        List<Coach> coaches = coachMapper.selectList(queryWrapper);
        for (Coach coach : coaches) {
            orders.setPayable(coach.getPrice());
        }
        ordersMapper.insert(orders);
    }

    @Override
    public void orderVip(OrdersVipDTO ordersVipDTO) {
        Vip vip = vipMapper.selectById(ordersVipDTO.getVipId());
        Orders orders = new Orders();
        orders.setNumber(String.valueOf(LocalDateTime.now().toEpochSecond(ZoneOffset.ofHours(8))));
        orders.setPayment(ordersVipDTO.getPayment());
        orders.setUserId(UserContext.getCurrentId());
        orders.setStatus(2);
        orders.setVipId(ordersVipDTO.getVipId());
        orders.setPayable(vip.getPrice());
        ordersMapper.insert(orders);

        Long currentId = UserContext.getCurrentId();
        User user = userMapper.selectById(currentId);
        Integer duration = vip.getDuration();
        if (user.getVip() == null){
            user.setVip(LocalDateTime.now().plusDays(duration));
        }else {
            user.setVip(user.getVip().plusDays(duration));
        }
//        rabbitTemplate.convertAndSend("amq.topic","pay.success",orders);
        userMapper.updateById(user);
    }

    @Override
    public List<MiniOrdersCourseVO> getCourse(Long uid,Integer status) {
        LambdaQueryWrapper<Orders> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(uid != null,Orders::getUserId,uid)
                .eq(Orders::getStatus, status);
        List<Orders> orders = ordersMapper.selectList(queryWrapper);
        ArrayList<MiniOrdersCourseVO> list = new ArrayList<>();
        for (Orders order : orders) {
            MiniOrdersCourseVO ordersCourseVO = new MiniOrdersCourseVO();
            ordersCourseVO.setNumber(order.getNumber());
            Course course = courseMapper.selectById(order.getCourseId());
            ordersCourseVO.setCourseName(course.getCourseName());
            Coach coach = coachMapper.selectById(order.getCoachId());
            ordersCourseVO.setCoachName(coach.getCoachName());
            Store store = storeMapper.selectById(course.getStoreId());
            ordersCourseVO.setStoreName(store.getStoreName());
            list.add(ordersCourseVO);
        }
        return list;
    }

    @Override
    public List<MiniOrdersVipVO> getVip(Long uid, Integer status) {
        LambdaQueryWrapper<Orders> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(uid != null,Orders::getUserId,uid)
                .eq(Orders::getStatus, status);
        List<Orders> orders = ordersMapper.selectList(queryWrapper);
        ArrayList<MiniOrdersVipVO> list = new ArrayList<>();
        for (Orders order : orders) {
            MiniOrdersVipVO ordersVipVO = new MiniOrdersVipVO();
            BeanUtils.copyProperties(order,ordersVipVO);
            Vip vip = vipMapper.selectById(order.getVipId());
            ordersVipVO.setVtype(vip.getType());
            list.add(ordersVipVO);
        }
        return list;
    }

    @Override
    public List<MiniOrdersCoachVO> getCoach(Long oid, Integer status) {
        LambdaQueryWrapper<Orders> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(oid != null,Orders::getId,oid)
                .eq(Orders::getStatus, status);
        List<Orders> orders = ordersMapper.selectList(queryWrapper);
        ArrayList<MiniOrdersCoachVO> list = new ArrayList<>();
        for (Orders order : orders) {
            MiniOrdersCoachVO ordersCoachVO = new MiniOrdersCoachVO();
            BeanUtils.copyProperties(order,ordersCoachVO);
            Coach coach = coachMapper.selectById(order.getCoachId());
            ordersCoachVO.setCoachName(coach.getCoachName());
            Store store = storeMapper.selectById(coach.getStoreId());
            ordersCoachVO.setStoreName(store.getStoreName());
            list.add(ordersCoachVO);
        }
        return list;
    }

    @Override
    public OrdersCourseVO getCourseById(Long oid, Integer status) {
        LambdaQueryWrapper<Orders> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(oid != null,Orders::getId,oid)
                .eq(Orders::getStatus, status);
        List<Orders> orders = ordersMapper.selectList(queryWrapper);
        OrdersCourseVO ordersCourseVO = new OrdersCourseVO();
        for (Orders order : orders) {
            BeanUtils.copyProperties(order,ordersCourseVO);

            Long currentId = UserContext.getCurrentId();
            User user = userMapper.selectById(currentId);
            ordersCourseVO.setUname(user.getName());
            Course course = courseMapper.selectById(order.getCourseId());
            ordersCourseVO.setCourseName(course.getCourseName());
            ordersCourseVO.setStartTime(course.getStartTime());
            ordersCourseVO.setEndTime(course.getEndTime());
            Store store = storeMapper.selectById(course.getStoreId());
            ordersCourseVO.setStoreName(store.getStoreName());
            Coach coach = coachMapper.selectById(order.getCoachId());
            ordersCourseVO.setCoachName(coach.getCoachName());
        }
        return ordersCourseVO;
    }

    @Override
    public OrdersCoachVO getCoachById(Long oid, Integer status) {
        LambdaQueryWrapper<Orders> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(oid != null,Orders::getId,oid)
                .eq(Orders::getStatus, status);
        List<Orders> orders = ordersMapper.selectList(queryWrapper);
        OrdersCoachVO ordersCoachVO = new OrdersCoachVO();
        for (Orders order : orders) {
            BeanUtils.copyProperties(order,ordersCoachVO);
            Long currentId = UserContext.getCurrentId();
            User user = userMapper.selectById(currentId);
            ordersCoachVO.setUname(user.getName());
            Coach coach = coachMapper.selectById(order.getCoachId());
            ordersCoachVO.setCoachName(coach.getCoachName());
            Store store = storeMapper.selectById(coach.getStoreId());
            ordersCoachVO.setStoreName(store.getStoreName());
        }
        return ordersCoachVO;
    }

    @Override
    public OrdersVipVO getVipById(Long oid, Integer status) {
        LambdaQueryWrapper<Orders> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(oid != null,Orders::getId,oid)
                .eq(Orders::getStatus, status);
        List<Orders> orders = ordersMapper.selectList(queryWrapper);
        OrdersVipVO ordersVipVO = new OrdersVipVO();
        for (Orders order : orders) {
            BeanUtils.copyProperties(order,ordersVipVO);
            Long currentId = UserContext.getCurrentId();
            User user = userMapper.selectById(currentId);
            ordersVipVO.setUname(user.getName());
            Vip vip = vipMapper.selectById(order.getVipId());
            ordersVipVO.setVtype(vip.getType());
        }
        return ordersVipVO;
    }

    @Override
    public void updateUser() {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        List<User> users = userMapper.selectList(queryWrapper);
        for (User user : users) {
            LocalDateTime vipTime = user.getVip();
            if (vipTime != null && vipTime.isBefore(LocalDateTime.now())){
                LambdaUpdateWrapper<User> userLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
                userLambdaUpdateWrapper.eq(User::getId,user.getId()).set(User::getVip,null);
                userMapper.update(user,userLambdaUpdateWrapper);
            }
        }
    }

}
